package array

import (
	"math/rand/v2"
)

// Search 类似php的array_search, 寻找切片元素并返回下标, 否则返回-1
func Search[T comparable](needle T, haystack []T) int {
	for i, e := range haystack {
		if e == needle {
			return i
		}
	}

	return -1
}

// Diff 类似php的array_diff, 返回切片的交集
func Diff[T comparable](a []T, list ...[]T) []T {
	set := make(map[T]bool)

	// 将 b 中的元素加入 set 中
	for _, l := range list {
		for _, e := range l {
			set[e] = true
		}
	}

	// 从 a 中删除 b 中存在的元素
	var diff []T
	for _, e := range a {
		if !set[e] {
			diff = append(diff, e)
		}
	}

	return diff
}

// Merge 类似php的array_merge, 合并多个切片
func Merge[T comparable](arrays ...[]T) []T {
	var result []T

	for _, arr := range arrays {
		result = append(result, arr...)
	}

	return result
}

// Map 类似php的array_map
func Map[T comparable, N comparable](fn func(T) N, arr []T) []N {
	result := make([]N, len(arr))

	for i, e := range arr {
		result[i] = fn(e)
	}

	return result
}

// In 类似php的in_array
func In[T comparable](needle T, haystack []T) bool {
	if haystack == nil || len(haystack) == 0 {
		return false
	}

	return Search(needle, haystack) >= 0
}

func IsValidIndex[T any](index int32, haystack []T) bool {
	return index >= 0 && index < int32(len(haystack))
}

func Shuffle[T comparable](slice []T) {
	for i := len(slice) - 1; i > 0; i-- {
		j := rand.IntN(i + 1)                   // Generate a random index between 0 and i
		slice[i], slice[j] = slice[j], slice[i] // Swap the elements
	}
}

// Unique 类似php的array_unique
func Unique[T comparable](slice []T) []T {
	keys := make(map[T]struct{}, len(slice))
	var list []T

	for _, entry := range slice {
		if _, ok := keys[entry]; !ok {
			keys[entry] = struct{}{}
			list = append(list, entry)
		}
	}

	return list
}

// Keys 类似php的array_keys
func Keys[T comparable, N any](m map[T]N) []T {
	keys := make([]T, 0, len(m))
	for k := range m {
		keys = append(keys, k)
	}
	return keys
}
